<?php

/**
 * tpAdmin [a web admin based ThinkPHP5]
 *
 * @author yuan1994 <tianpian0805@gmail.com>
 * @link http://tpadmin.yuan1994.com/
 * @copyright 2016 yuan1994 all rights reserved.
 * @license http://www.apache.org/licenses/LICENSE-2.0
 */
//------------------------
// 公共函数
//-------------------------

use think\Session;
use think\Response;
use think\Request;
use think\Url;
use think\Db;

/**
 * CURLFILE 兼容性处理 php < 5.5
 * 一定不要修改、删除，否则 curl 可能无法上传文件
 */
if (!function_exists('curl_file_create')) {

    function curl_file_create($filename, $mimetype = '', $postname = '') {
        return "@$filename;filename="
                . ($postname ?: basename($filename))
                . ($mimetype ? ";type=$mimetype" : '');
    }

}

function urlencod($val) {
    return urlencode($val);
}

function in_strpos($val, $arr) {
    return strpos('!' . $arr, $val);
}

function strip($str) {
    $str = str_replace(array('&lt;p&gt;', '&lt;/p&gt;', '&lt;br&gt;', '&lt;br/&gt;','&amp;nbsp;','&nbsp;'), "", $str);
//$str=htmlspecialchars($str);
    return strip_tags($str);
}

/**
 * flash message
 *
 * flash("?KEY") 判断是否存在flash message KEY 返回bool值
 * flash("KEY") 获取flash message，存在返回具体值，不存在返回null
 * flash("KEY","VALUE") 设置flash message
 * @param string $key
 * @param bool|string $value
 * @return bool|mixed|null
 */
function flash($key, $value = false) {
    $prefix = 'flash_';
    // 判断是否存在flash message
    if ('?' == substr($key, 0, 1)) {
        return Session::has($prefix . substr($key, 1));
    } else {
        $flash_key = $prefix . $key;
        if (false === $value) {
            // 获取flash
            $ret = Session::pull($flash_key);

            return null === $ret ? null : unserialize($ret);
        } else {
            // 设置flash
            return Session::set($flash_key, serialize($value));
        }
    }
}

/**
 * 表格排序筛选
 * @param string $name  单元格名称
 * @param string $field 排序字段
 * @return string
 */
function sort_by($name, $field = '') {
    $sort = Request::instance()->param('_sort');
    $param = Request::instance()->get();
    $param['_sort'] = ($sort == 'asc' ? 'desc' : 'asc');
    $param['_order'] = $field;
    $url = Url::build(Request::instance()->action(), $param);

    return Request::instance()->param('_order') == $field ?
            "<a href='{$url}' title='点击排序' class='sorting-box sorting-{$sort}'>{$name}</a>" :
            "<a href='{$url}' title='点击排序' class='sorting-box sorting'>{$name}</a>";
}

/**
 * 用于高亮搜索关键词
 * @param string $string 原文本
 * @param string $needle 关键词
 * @param string $class  span标签class名
 * @return mixed
 */
function high_light($string, $needle = '', $class = 'c-red') {
    return $needle !== '' ? str_replace($needle, "<span class='{$class}'>" . $needle . "</span>", $string) : $string;
}

/**
 * 无极限生成树
 * @param array $arr
 * @param int $pid          父id
 * @param $me
 * @return array
 */
function generateTree($arr, $pid, $step) {
    global $tree;
    foreach ($arr as $key => $val) {
        if ($val['pid'] == $pid) {
            $flg = str_repeat('└―', $step);
            $val['name'] = $flg . $val['name'];
            $tree[] = $val;
            generateTree($arr, $val['id'], $step + 1);
        }
    }
    return $tree;
}

/*
  function generateTreeOne($arr,$pid,$step,$tree=array()){


  foreach($arr as $key=>$val) {

  if($val['pid'] == $pid) {
  echo $val['id'].'->'.$pid.'->'.$val['pid']."<br>";
  $flg = str_repeat('└―',$step);
  $val['name'] = $flg.$val['name'];
  $tree[] = $val;
  json_encode($tree); echo "<br>";
  generateTreeOne($arr , $val['id'] ,$step+1,$tree);
  }
  }
  #return json_encode($tree);
  }* */

function generateTreeOne($list, $parent, $level = 0) {
    $treec = array();
    foreach ($list as $value) {
        if ($value['pid'] == $parent) {
            $value['level'] = $level;
            $value['name'] = str_repeat("└―", $value['level']) . $value['name'];
            $treec[] = $value;
            $treec = array_merge($treec, generateTreeOne($list, $value['id'], $level + 1));
        }
    }

    return $treec;
}

/**
 * 把二维数组的id转换成键值
 * @param $items
 */
function setArrKeyId($arr) {
    if (!isset($arr))
        return false;
    $arrs = [];
    foreach ($arr as $key => $value) {
        $arrs[$value['id']] = $value;
    }
    return $arrs;
}

function setArrKeyuserId($arr) {
    if (!isset($arr))
        return false;
    $arrs = [];
    foreach ($arr as $key => $value) {
        $arrs[$value['userid']] = $value;
    }
    return $arrs;
}

function setArrKeyuserUserId($arr) {
    if (!isset($arr))
        return false;
    $arrs = [];
    foreach ($arr as $key => $value) {
        $arrs[$value['userid']] = $value;
    }
    return $arrs;
}

/**
 * 获取一个表的数据 通过id集合
 * @param $tablename
 * @param $ids
 * @param null $field
 * @return bool
 */
function getListByIds($tablename, $ids, $field = null) {
	
    if (!isset($tablename))
        return false;
    if (!isset($ids))
        return false;
    if (is_array($ids))
        $ids = implode(',', $ids);
	$ids = $ids.'0';

    $model = Db::name($tablename);
    $List = $model->where("id in ($ids)")->field($field)->select();
    return $List;
}

/**
 * 通过 用户id获取角色
 * @param $uid
 * @return null|string
 */
function getRoleNameByUid($uid) {
    $AdminRole = new \app\common\model\AdminRole(); //实例化 角色
    $Roles = $AdminRole->getRoleByUid($uid); //获取用户角色列表
    $RolesName = null;
    foreach ($Roles as $Role) {
        $RolesName .= $Role['name'] . ',';
//        $RolesName.=$Role['name'];
    }
    return $RolesName;
//    var_dump($RolesName);die;
}

/*
 *
 * lengthConversionKm
 * @param $leng 长度
 * 百度地图是按米算的所以需要 米换算成公里
 */

function lengthConversionKm($leng) {
    $leng = $leng / 1000;
    return $leng;
}

/*
 *
 * lengthConversion
 * @param $leng 长度
 * 百度地图是按米算的所以需要 公里换算成米
 */

function lengthConversion($leng) {
    $leng = $leng / 1000;
    return $leng;
}

/**
 * 用于显示状态操作按钮
 * @param int $status        0|1|-1状态
 * @param int $id            对象id
 * @param string $field      字段，默认id
 * @param string $controller 默认当前控制器
 * @return string
 */
function show_status($status, $id, $field = 'id', $controller = '') {
    $controller === '' && $controller = Request::instance()->controller();
    switch ($status) {
        // 恢复
        case 0 :
            $ret = '<a href="javascript:;" onclick="ajax_req(\'' . Url::build($controller . '/resume', [$field => $id]) . '\',{},change_status,[this,\'resume\'])" class="label label-success radius" title="点击恢复">恢复</a>';
            break;
        // 禁用
        case 1 :
            $ret = '<a href="javascript:;" onclick="ajax_req(\'' . Url::build($controller . '/forbid', [$field => $id]) . '\',{},change_status,[this,\'forbid\'])" class="label label-warning radius" title="点击禁用">禁用</a>';
            break;
        // 还原
        case -1 :
            $ret = '<a href="javascript:;" onclick="ajax_req(\'' . Url::build($controller . '/recycle', [$field => $id]) . '\')" class="label label-secondary radius" title="点击还原">还原</a>';
            break;
        /*         * **打个补丁 预防id不等于2**** */
        default:
            $ret = '<a href="javascript:;" onclick="ajax_req(\'' . Url::build($controller . '/resume', [$field => $id]) . '\',{},change_status,[this,\'resume\'])" class="label label-success radius" title="点击恢复">状态错误点击恢复</a>';
        /*         * **打个补丁 end**** */
    }

    return $ret;
}

/**
 * 显示状态
 * @param int $status     0|1|-1
 * @param bool $imageShow true只显示图标|false只显示文字
 * @return string
 */
function get_status($status, $imageShow = true) {
    switch ($status) {
        case 0 :
            $showText = '禁用';
            $showImg = '<i class="Hui-iconfont c-warning status" title="禁用">&#xe631;</i>';
            break;
        case -1 :
            $showText = '删除';
            $showImg = '<i class="Hui-iconfont c-danger status" title="删除">&#xe6e2;</i>';
            break;
        case 1 :
        default :
            $showText = '正常';
            $showImg = '<i class="Hui-iconfont c-success status" title="正常">&#xe615;</i>';
    }

    return ($imageShow === true) ? $showImg : $showText;
}

/**
 * 框架内部默认ajax返回
 * @param string $msg      提示信息
 * @param string $redirect 重定向类型 current|parent|''
 * @param string $alert    父层弹框信息
 * @param bool $close      是否关闭当前层
 * @param string $url      重定向地址
 * @param string $data     附加数据
 * @param int $code        错误码
 * @param array $extend    扩展数据
 */
function ajax_return_adv($msg = '操作成功', $redirect = 'parent', $alert = '', $close = false, $url = '', $data = '', $code = 0, $extend = []) {
    $extend['opt'] = [
        'alert' => $alert,
        'close' => $close,
        'redirect' => $redirect,
        'url' => $url,
    ];

    return ajax_return($data, $msg, $code, $extend);
}

/**
 * 返回错误json信息
 */
function ajax_return_adv_error($msg = '', $code = 1, $redirect = '', $alert = '', $close = false, $url = '', $data = '', $extend = []) {
    return ajax_return_adv($msg, $alert, $close, $redirect, $url, $data, $code, $extend);
}

/**
 * ajax数据返回，规范格式
 * @param array $data   返回的数据，默认空数组
 * @param string $msg   信息
 * @param int $code     错误码，0-未出现错误|其他出现错误
 * @param array $extend 扩展数据
 */
function ajax_return($data = [], $msg = "", $code = 0, $extend = []) {
    $ret = ["code" => $code, "msg" => $msg, "data" => $data];
    $ret = array_merge($ret, $extend);

    return Response::create($ret, 'json');
}

/**
 * 返回标准错误json信息
 */
function ajax_return_error($msg = "出现错误", $code = 1, $data = [], $extend = []) {
    return ajax_return($data, $msg, $code, $extend);
}

/**
 * 从二维数组中取出自己要的KEY值
 * @param  array $arrData
 * @param string $key
 * @param $im true 返回逗号分隔
 * @return array
 */
function filter_value($arrData, $key, $im = false) {
    $re = [];
    foreach ($arrData as $k => $v) {
        if (isset($v[$key]))
            $re[] = $v[$key];
    }
    if (!empty($re)) {
        $re = array_flip(array_flip($re));
        sort($re);
    }

    return $im ? implode(',', $re) : $re;
}

/**
 * 重设键，转为array(key=>array())
 * @param array $arr
 * @param string $key
 * @return array
 */
function reset_by_key($arr, $key) {
    $re = [];
    foreach ($arr as $v) {
        $re[$v[$key]] = $v;
    }

    return $re;
}

/**
 * 节点遍历
 *
 * @param        $list
 * @param string $pk
 * @param string $pid
 * @param string $child
 * @param int    $root
 *
 * @return array
 */
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0) {
    // 创建Tree
    $tree = [];
    if (is_array($list)) {
        // 创建基于主键的数组引用
        $refer = [];
        foreach ($list as $key => $data) {
            if ($data instanceof \think\Model) {
                $list[$key] = $data->toArray();
            }
            $refer[$data[$pk]] = & $list[$key];
        }
        foreach ($list as $key => $data) {
            // 判断是否存在parent
            if (!isset($list[$key][$child])) {
                $list[$key][$child] = [];
            }
            $parentId = $data[$pid];
            if ($root == $parentId) {
                $tree[] = & $list[$key];
            } else {
                if (isset($refer[$parentId])) {
                    $parent = & $refer[$parentId];
                    $parent[$child][] = & $list[$key];
                }
            }
        }
    }

    return $tree;
}

/**
 * 统一密码加密方式，如需变动直接修改此处
 * @param $password
 * @return string
 */
function password_hash_tp($password) {
    return hash("md5", trim($password));
}

/**
 * 生成随机字符串
 * @param string $prefix
 * @return string
 */
function get_random($prefix = '') {
    return $prefix . base_convert(time() * 1000, 10, 36) . "_" . base_convert(microtime(), 10, 36) . uniqid();
}

/**
 * 获取自定义配置
 * @param string|int $name 配置项的key或者value，传key返回value，传value返回key
 * @param string $conf
 * @param bool $key        传递的是否是配置键名，默认是，则返回配置信息
 * @return int|string
 */
function get_conf($name, $conf, $key = true) {
    $arr = config("conf." . $conf);
    if ($key)
        return $arr[$name];
    foreach ($arr as $k => $v) {
        if ($v == $name) {
            return $k;
        }
    }
}

/**
 * 多维数组合并（支持多数组）
 * @return array
 */
function array_merge_multi() {
    $args = func_get_args();
    $array = [];
    foreach ($args as $arg) {
        if (is_array($arg)) {
            foreach ($arg as $k => $v) {
                if (is_array($v)) {
                    $array[$k] = isset($array[$k]) ? $array[$k] : [];
                    $array[$k] = array_merge_multi($array[$k], $v);
                } else {
                    $array[$k] = $v;
                }
            }
        }
    }

    return $array;
}

/**
 * 将list_to_tree的树还原成列表
 * @param array $tree
 * @param string $child
 * @param string $order
 * @param int $level
 * @param null $filter
 * @param array $list
 * @return array
 */
function tree_to_list($tree, $filter = null, $child = '_child', $order = 'id', $level = 0, &$list = []) {
    if (is_array($tree)) {
        if (!is_callable($filter)) {
            $filter = function (&$refer, $level) {
                $refer['level'] = $level;
            };
        }
        foreach ($tree as $key => $value) {
            $refer = $value;
            unset($refer[$child]);
            $filter($refer, $level);
            $list[] = $refer;
            if (isset($value[$child])) {
                tree_to_list($value[$child], $filter, $child, $order, $level + 1, $list);
            }
        }
    }

    return $list;
}

/**
 * 对查询结果集进行排序
 * @access public
 * @param array $list   查询结果
 * @param string $field 排序的字段名
 * @param array $sortBy 排序类型
 *                      asc正向排序 desc逆向排序 nat自然排序
 * @return array|bool
 */
function list_sort_by($list, $field, $sortBy = 'asc') {
    if (is_array($list)) {
        $refer = $resultSet = [];
        foreach ($list as $i => $data)
            $refer[$i] = &$data[$field];
        switch ($sortBy) {
            case 'asc': // 正向排序
                asort($refer);
                break;
            case 'desc': // 逆向排序
                arsort($refer);
                break;
            case 'nat': // 自然排序
                natcasesort($refer);
                break;
        }
        foreach ($refer as $key => $val)
            $resultSet[] = &$list[$key];

        return $resultSet;
    }

    return false;
}

/**
 * 格式化字节大小
 * @param  number $size      字节数
 * @param  string $delimiter 数字和单位分隔符
 * @return string            格式化后的带单位的大小
 */
function format_bytes($size, $delimiter = '') {
    $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
    for ($i = 0; $size >= 1024 && $i < 5; $i++)
        $size /= 1024;

    return round($size, 2) . $delimiter . $units[$i];
}

/**
 * 生成一定长度的UUID
 *
 * @param int $length
 *
 * @return string
 */
function get_uuid($length = 16) {
    mt_srand((double) microtime() * 10000);
    $uuid = sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
    $str = base64_encode($uuid);
    return substr($str, mt_rand(0, strlen($str) - $length), $length);
}

/**
 * 根据模型名称获取模型
 *
 * @param $modelName
 *
 * @return \think\Model|\think\db\Query
 */
function get_model($modelName) {
    if (false !== strpos($modelName, '\\')) {
        // 指定模型类
        $db = new $modelName;
    } else {
        try {
            $db = \think\Loader::model($modelName);
        } catch (\think\exception\ClassNotFoundException $e) {
            $db = \think\Db::name($modelName);
        }
    }

    return $db;
}

/*
 * 按条件查询出所有题目
 * $question_bank 确定选择那个题库 0是直接大题库
 * $types 类型
 * $topicid 题目id 针对只需要查几条数据的时候用
 */

function query_all($types, $question_bank = 0, $topicid = 0) {
    $abs_array = array(); //分组用的
    $abstracts = array(); //最终生成的数组
    $condition = array(); //sql 执行左往右
    $keys = array(); //在不破坏原来逻辑的情况下选择 获取id 再查一次库
    if ($question_bank) {
        $questype = questiondb($question_bank);
        $questype['d_data'] = unserialize($questype['d_data']);
        if (empty($questype['d_data'])) {
            return 2;
        }
        foreach ($questype['d_data'] as $kc => $v) {

            $keys[] = $kc;
        }
        if (!empty($keys[0])) {
            $condition['id'] = ['in', implode(',', $keys)];
        }
    }
    if ($topicid) {
        $condition['id'] = ['in', implode(',', $topicid)];
    }
    $condition['q_typeid'] = ['in', $types];
    $questype = Db::name('questions')->field('id,q_typeid,q_question,q_status,q_select,q_answer,q_knowsid,q_qbankid')->where($condition)->select();
    return $questype;
}

function strFilter($str) {
    $arr = array('`', '~', '!', '！', '<p>', '</p>', '#', '$', '￥', '%', '^', '……', '&', '*', '\\', '[', ']', '、', '?', '？', 'eva', ' ', '	', 'inser', 'updat', 'selec', 'form', '(', ')', '@', 'scrip', '<', '>', 'and', 'or', 'exe', '|', '{', '}');
    $str = str_replace($arr, '', $str);
    return $str;
}

/**
 * 根据试题类型 typeid 题库id dbid 知识点id knowsid 在大题库进行抽题
 */
function queryQuestionByparam($param) {
    $abs_array = array(); //分组用的
    $abstracts = array(); //最终生成的数组\
    //    var_dump($param);die;
    if (isset($param['dbid'])) {
        $condition['q_qbankid'] = ['in', $param['dbid']];
    }
    if (isset($param['knowsid'])) {
        $condition['q_knowsid'] = ['in', $param['knowsid']];
    }
    if (isset($param['typeid'])) {
        $condition['q_typeid'] = ['in', $param['typeid']];
    }
    if (isset($param['q_question'])) {
        $condition['q_question'] = ['like', '%' . $param['q_question'] . '%'];
    }
    //    $questype=Db::name('questions')->field('id,q_typeid,q_question,q_status,q_select,q_answer,q_knowsid,q_qbankid,q_describe')->where($condition)->paginate(10);
    $questype = Db::name('questions')->field('id,q_typeid,q_question,q_status,q_select,q_answer,q_knowsid,q_qbankid,q_describe')->where($condition)->select();
    return $questype;
}

/*
 * 按条件查询出所有题目
 * $question_bank 确定选择那个题库 0是直接大题库
 * $types 类型
 */

function questiondb($id = 0) {
    $questiondb = Db::name('question_db')->field('*');
    if ($id) {
        $questiondb->where(['id' => $id]);
    }
    return $questiondb->find();
}

/*
 * random_ques 初级抽题
 * $types 抽题配置
 * $style 返回的类型 0是返回详细 1是返回id
 * $question_bank 确定选择那个题库 0是直接大题库
 */

function random_ques($types, $style = 0, $question_bank = 0) {
    $abs_array = array(); //分组用的
    $abstracts = array(); //最终生成的数组
    $key = array();
    foreach ($types as $k => $v) {//这里是获取 题目类型id  虽然 array_keys 简单粗暴但是考虑 没必要查询空值
        if (!empty($v[0])) {
            $key[] = $k;
        }
    }
    if (empty($key[0]))
        return false;

    $random = query_all(implode(',', $key), $question_bank);

    if ($random == 2) {
        $random = query_all(implode(',', $key), 0);
    }
#[$v['q_status']]
    foreach ($random as $v) {
        $abs_array[$v['q_typeid']][] = $v;
    }

    if ($style) {//外层加循环 代码重复但是不用多次判断
        foreach ($types as $kc => $vc) {
            #foreach($vc as $ks=>$vs){
            if (empty($abs_array[$kc]))
                break;
            $num = count($abs_array[$kc]);
            if ($vc['0'] > $num) {
                $vc['0'] = $num;
            }

            foreach (array_rand($abs_array[$kc], $vc['0']) as $vid) {//按类型 分别随机出需要的数组
                if (empty($abs_array[$kc][$vid]))
                    break;

                $abstracts[$kc][] = $abs_array[$kc][$vid]['id'];
            }
            #}
        }
    } else {
        foreach ($types as $kc => $vc) {
            if (empty($abs_array[$kc]))
                break;
            foreach (array_rand($abs_array[$kc], $vc['0']) as $vid) {//按类型 分别随机出需要的数组
                $abstracts[$kc][] = $abs_array[$kc][$vid];
            }
        }
    }
    return $abstracts;
}

/*
 * random_ques_pro 按比例抽题
 * $types 抽题配置
 * $style 返回的类型 0是返回详细 1是返回id
 * $question_bank 确定选择那个题库 0是直接大题库
 * $ratio比例规则
 */

function random_ques_pro1($style = 0, $question_bank = 0, $ratio) {
    $abs_array = array(); //分组用的
    $abstracts = array(); //最终生成的数组
    $key = array();

    foreach ($ratio as $k => $v) {//这里是获取 题目类型id  虽然 array_keys 简单粗暴但是考虑 没必要查询空值
        if (!empty($v)) {
            $key[] = $k;
        }
    }
    if (empty($key[0]))
        return false;

    $random = query_all(implode(',', $key), $question_bank);

    if ($random == 2) {
        $random = query_all(implode(',', $key), 0);
    }
#[$v['q_status']]
    foreach ($random as $v) {
        $abs_array[$v['q_typeid']][$v['q_knowsid']][] = $v['id'];
    }

    $rule = array();
    $detailed = array();
    if ($style) {//外层加循环 代码重复但是不用多次判断
        foreach ($ratio as $kr => $vr) {
            $vr = trim($vr);
            $rule = explode("\r\n", $vr);
            foreach ($rule as $vk) {
                $detailed = explode(":", $vk);

                if (empty($abs_array[$kr][$detailed[0]]))
                    break;
                $num = count($abs_array[$kr][$detailed[0]]);
                $detailed[1] = empty($detailed[1]) ? 0 : (int) $detailed[1];

                if ($detailed[1] > $num) {
                    $detailed[1] = $num;
                }

                foreach (array_rand($abs_array[$kr][$detailed[0]], $detailed[1]) as $vid) {//按类型 分别随机出需要的数组
                    $abstracts[$kr][] = $abs_array[$kr][$detailed[0]][$vid];
                }
            }
        }
    } else {
        foreach ($ratio as $kr => $vr) {
            $vr = trim($vr);
            $rule = explode("\r\n", $vr);
            foreach ($rule as $vk) {
                $detailed = explode(":", $vk);

                if (empty($abs_array[$kr][$detailed[0]]))
                    break;
                if ($detailed[1] > $num) {
                    $detailed[1] = $num;
                }

                foreach (array_rand($abs_array[$kr][$detailed[0]], $detailed[1]) as $vid) {//按类型 分别随机出需要的数组
                    $abstracts[$kr][] = $abs_array[$kr][$detailed[0]][$vid];
                }
            }
        }
    }

    return $abstracts;
}

/*
 * 按配置题型 抽题
 * $types = [1=>['数量','分类id','类型id']]
 */

function small_question_bank($types, $style = 0, $question_bank = 0) {
    $abs_array = array(); //分组用的
    $abstracts = array(); //最终生成的数组
    $key = array();
    foreach ($types as $k => $v) {//这里是获取 题目类型id  虽然 array_keys 简单粗暴但是考虑 没必要查询空值
        if (!empty($v[0])) {
            $key[] = $k;
        }
    }
    if (empty($key[0]))
        return false;

    $random = query_all(implode(',', $key), $question_bank);
    foreach ($random as $v) {//q_typeid q_qbankid 题库id 知识点q_qbankid
        $abs_array[$v['q_typeid']][$v['q_qbankid']][$v['q_knowsid']][] = $v;
    }

    if ($style) {//外层加循环 代码重复但是不用多次判断
        foreach ($types as $kc => $vc) {
            #foreach($vc as $ks=>$vs){
            if (empty($abs_array[$kc]))
                break;
            foreach (array_rand($abs_array[$kc], $vc['0']) as $vid) {//按类型 分别随机出需要的数组
                $abstracts[$kc][] = $abs_array[$kc][$vid]['id'];
            }
            #}
        }
    } else {
        foreach ($types as $kc => $vc) {
            if (empty($abs_array[$kc]))
                break;
            foreach (array_rand($abs_array[$kc][$vc['1']][$vc['2']], $vc['0']) as $vid) {//按类型 分别随机出需要的数组
                $abstracts[$kc][] = $abs_array[$kc][$vc['1']][$vc['2']][$vid];
            }
        }
    }
    return $abstracts;
}

/*
 * 获取ip
 */

function getIP() {
    if (getenv('HTTP_CLIENT_IP')) {
        $ip = getenv('HTTP_CLIENT_IP');
    } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
        $ip = getenv('HTTP_X_FORWARDED_FOR');
    } elseif (getenv('HTTP_X_FORWARDED')) {
        $ip = getenv('HTTP_X_FORWARDED');
    } elseif (getenv('HTTP_FORWARDED_FOR')) {
        $ip = getenv('HTTP_FORWARDED_FOR');
    } elseif (getenv('HTTP_FORWARDED')) {
        $ip = getenv('HTTP_FORWARDED');
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    return $ip;
}

//获取后缀
function get_extension($file) {
    return pathinfo($file, PATHINFO_EXTENSION);
}


//任务类型

function getTaskType() {
    $arr = [];
    $TaskTypeModel = new \app\common\model\TaskType();
    $arr = $TaskTypeModel->getListByArg(['status'=>1,'isdelete'=>0],'type_name,id');
    return $arr;
}

//任务类型
function typelist() {
    $arr = [
        '0' => '无需文件',
        'paper' => '试卷任务', //练题页面
        'qbank' => '指定练题任务', //练题页面
        '1' => '练题任务', //练题页面
            //'curseware'=>'课程',
    ];
    return $arr;
}

//任务最终地址
function linkurl($file, $id) {
    $arr = [
        '0' => '',
        'paper' => '/mobile/Paper/makePaper/id/' . $id . '.html',
        'qbank' => '/mobile/practice/matching/id/' . $id . '.html',
        '1' => '/mobile/practice/index.html',
    ];
    return $arr[$file];
}

/**
 * 导出数据为excel表格
 * @param $data    一个二维数组,结构如同从数据库查出来的数组
 * @param $title   excel的第一行标题,一个数组,如果为空则没有标题
 * @param $filename 下载的文件名
 * @examlpe 
  $stu = M ('User');
  $arr = $stu -> select();
  exportexcel($arr,array('id','账户','密码','昵称'),'文件名!');
 */
function exportexcel($data = array(), $title = array(), $filename = 'report') {


    header("Content-type:application/octet-stream");
    header("Accept-Ranges:bytes");
    header("Content-type:application/vnd.ms-excel");
    header("Content-Disposition:attachment;filename=" . $filename . ".xls");
    header("Pragma: no-cache");
    header("Expires: 0");
    //导出xls 开始
    if (!empty($title)) {
        foreach ($title as $k => $v) {
            $title[$k] = iconv("UTF-8", "GB2312", $v);
        }
        $title = implode("\t", $title);
        echo "$title\n";
    }
    if (!empty($data)) {
        foreach ($data as $key => $val) {
            foreach ($val as $ck => $cv) {
                $cv = str_replace(array("\r", "\t", '\n'), "", $cv);
                $data[$key][$ck] = iconv("UTF-8", "GB2312", $cv);
            }
            $data[$key] = implode("\t", $data[$key]);
        }
        echo implode("\n", $data);
    }
}

/**
 * 验证规则扩展
 */
\think\Validate::extend([
    // 验证字段是否在模型中存在
    'checkExist' => function($value, $rule, $data, $field) {
        if (is_string($rule)) {
            $rule = explode(',', $rule);
        }
        $db = get_model($rule[0]);
        $key = isset($rule[1]) ? $rule[1] : $field;

        if (strpos($key, '^')) {
            // 支持多个字段验证
            $fields = explode('^', $key);
            foreach ($fields as $key) {
                $map[$key] = $data[$key];
            }
        } elseif (strpos($key, '=')) {
            parse_str($key, $map);
        } else {
            $map[$key] = $data[$field];
        }

        $pk = strval(isset($rule[3]) ? $rule[3] : $db->getPk());
        if (isset($rule[2])) {
            $map[$pk] = ['neq', $rule[2]];
        } elseif (isset($data[$pk])) {
            $map[$pk] = ['neq', $data[$pk]];
        }

        if ($db->where($map)->field($pk)->find()) {
            return true;
        }
        return false;
    }
]);

function creditsetting($val, $statu = 0) {
    $rype = [
        '1' => '日常练习',
        '2' => '学习中心反馈',
        '3' => '试卷',
        '4' => '模拟卷',
        '5' => '正式考试',
    ];
    if ($statu) {
        return $rype;
    }
    if (empty($rype[$val]))
        $rype[$val] = '未知';
    return $rype[$val];
}


/*
 * 统计登录天数
 */

function days($pid = 0, $identity_id = 0, $statime = 0, $endtime = 0) {

    $signCheck = new \app\common\model\SignCheck();
    $daysnum = $signCheck->signumberdays($pid, $identity_id, $statime, $endtime);

    return count($daysnum);
}

//获取子分类ID
function getChildrenId($pid=0){
	global $ChildrenId;
    $plaform = new \app\common\model\Plaform();
    $sortresult=$plaform->getListByArg(['parentid'=>$pid],'id,parentid');
		if(empty($sortresult[0])){
			//如果没有数据就表示没有下一级了就直接停止往下执行
			return false;
		}
		foreach($sortresult as $v){
			$ChildrenId=$ChildrenId.",".$v['id'];
			getChildrenId($v['id']);
		}
    return $ChildrenId;
}

//获取子分类ID
function getChildrenId_name($pid=0){
	global $ChildrenId;
    $plaform = new \app\common\model\Plaform();
    $sortresult=$plaform->getListByArg(['id'=>$pid],'id,parentid,real');
		if(empty($sortresult[0])){
			//如果没有数据就表示没有下一级了就直接停止往下执行
			return false;
		}
		foreach($sortresult as $v){
			
			$ChildrenId=$v['real']."&nbsp;".$ChildrenId;
			getChildrenId_name($v['parentid']);
	
		}
		
    return trim($ChildrenId);
}

/*
 * 统计登录天数
 */

function abnchecdays($pid = 0, $identity_id = 0, $statime = 0, $endtime = 0) {
    //{:abnchecdays($vo.pid,$vo.identity_id,$startime[1],$endtime[1])}
    $signCheck = new \app\common\model\SignCheck();
    $daysnum = $signCheck->abncheckdats($pid, $identity_id, $statime, $endtime);

    if (empty($daysnum['num'])) {
        $daysnum['num'] = 0;
    }    return $daysnum['num'];
}


/**
     * 签到详情备注查询
     * @return mixed
     */
    function RemDetretrieve($id=0,$type=0)
    {
		$SignDoc = new \app\common\model\SignDoc();
		$remarks = $SignDoc->where("signid='{$id}'")->select();
		if($type==2){
			$src=$remarks[0]['address'];
		} else {
			$src=$remarks[0]['conter'];
		}
        return $src;
    }

    // 获取所有平台reg
function AdmingetAllplaformReg(){
    $result = Db::name('plaform')->field('id,parentid parent_id,admin_reg,level')->where(['status'=>1])->select();
    return $result;
}
// 传一个id获取下面所有子集数据
function AdmingetChildPloformReg($arr, $id=0){
    $resultArray = [];

    foreach($arr as $v){
        if($v['parent_id']==$id){
            if($v['admin_reg']){
                $resultArray[] = $v['admin_reg'];    
            }
            array_merge(getChildPloformReg($arr,$v['id']));
        }
        if($v['id']==$id){
            $resultArray[] = $v['admin_reg'];    
        }
    }
    return $resultArray;
}